热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

出库管理|零件设计中的状态模式学习心得与应用分析

篇首语:本文由编程笔记#小编为大家整理,主要介绍了设计模式学习笔记之状态模式相关的知识,希望对你有一定的参考价值。 什么是状态模式呢? 允许一个对象在其内部状态改变时改变它的行为。对象看

篇首语:本文由编程笔记#小编为大家整理,主要介绍了设计模式学习笔记之状态模式相关的知识,希望对你有一定的参考价值。


什么是状态模式呢?

允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。。。是不是听起来显示在内部进行零件调换的感觉,其实是有点类似这种想法的,只不过调换的零件就是封装好的状态。

让我们来举个例子




在我还上学的时候,寝室楼下有一台这样的自动贩售机,专门卖饮料。每天晚上寝室关门之后口渴了,在这里面买点饮料喝喝还是很方便的。

下面用程序来模拟一下这个售货机:


可乐售货机类:


/**
*
* 可乐自动贩售机类
* @author birdlove1987
*
*/
public class VendingMachine

//售空
final static int SoldOutState = 0;

//在售
final static int OnReadyState = 1;

//有币
final static int HasCoin = 2;

//出货
final static int SoldState = 3;
//售货机状态
private int state = SoldOutState;

//机内可乐数量
private int count = 0;
//构造函数,初始化自动贩售机
public VendingMachine(int count)

this.count = count;
if (count > 0)
state = OnReadyState;


//向贩售机投币函数
public void insertCoin()

switch (state)

case SoldOutState:
System.out.println("请不要投币了,售货机里已经没有可乐了!");
break;
case OnReadyState:
state = HasCoin;
System.out.println("投币成功,请按出货按钮!");
break;
case HasCoin:
System.out.println("售货机里以及有硬币了,请勿重复投币!");
break;
case SoldState:
System.out.println("正在出货请勿投币!");
break;


//贩售机退币函数
public void returnCoin()

switch (state)

case SoldOutState:
System.out.println("您还没有投币!");
break;
case OnReadyState:
System.out.println("您还没有投币!");
break;
case HasCoin:
System.out.println("请在退币口收好您的硬币");
state = OnReadyState;
break;
case SoldState:
System.out.println("可乐已售出,不能退币");
break;


//按出可乐按钮函数
public void pressButton()

switch (state)

case SoldOutState:
System.out.println("对不起,可乐已售空!");
break;
case OnReadyState:
System.out.println("请您先投币!");
break;
case HasCoin:
System.out.println("请稍等,出可乐中!");
state = SoldState;
appearCola();
break;
case SoldState:
System.out.println("可乐已出,如想再次购买请再次投币!");
break;


//售货机出可乐函数
private void appearCola()

count = count - 1;
System.out.println("出货口,滚出了一瓶可乐!");
if (count > 0)

state = OnReadyState;

else

System.out.println("对不起,可乐已经售空了,请勿在投币!");
state = SoldOutState;


//打印目前售货机的状态
public void printState()

switch (state)

case SoldOutState:
System.out.println("=========售空=========");
break;
case OnReadyState:
System.out.println("=========售卖中=========");
break;
case HasCoin:
System.out.println("=========已投币=========");
break;
case SoldState:
System.out.println("=========出货中=========");
break;





写个测试类来测试一下

测试类


/**
* 测试类
* @author birdlove1987
*
*/
public class MainTest
public static void main(String[] args)

//创建售货机实例,并且只放入一瓶可乐
VendingMachine mVendingMachine=new VendingMachine(1);


//打印售货机状态
mVendingMachine.printState();

//投币
mVendingMachine.insertCoin();

//打印售货机状态
mVendingMachine.printState();

//按出货按钮
mVendingMachine.pressButton();


//打印售货机状态
mVendingMachine.printState();

//投币
mVendingMachine.insertCoin();

//打印售货机状态
mVendingMachine.printState();

//按出货按钮
mVendingMachine.pressButton();

//打印售货机状态
mVendingMachine.printState();






嗯!模拟成功了!好像感觉还不错呢!不过买了一段时间,你可能发现,如果不搞一些促销活动,更本就搞不过那些有促销的商家!




所以自动售货机也要搞一个“再来一瓶”的活动啊!

但是!!!如果现在直接在自动售货机的类上去直接修改,就违背了软件设计里的“开-闭原则”了,破坏了我们已经闭合的类。所以现在看来,这种设计并不好。。

下面就轮到状态设计模式登场啦,我们从新构建类,这次以状态为类,来构建。

首先定义一下状态接口


/***
* 状态接口
* @author birdlove1987
*
*/
public interface State

//投币函数
public void insertCoin();

//退币函数
public void returnCoin();

//按出可乐按钮函数
public void pressButton();

//出可乐函数
public void appearCola();

//打印状态函数
public void printState();




再来定义状态类


/***
* 在售状态类
* @author birdlove1987
*
*/
public class OnReadyState implements State

//贩售机引用
private VendingMachine mVendingMachine;

//构造函数初始化
public OnReadyState(VendingMachine mVendingMachine)

this.mVendingMachine=mVendingMachine;


@Override
public void insertCoin()

// TODO Auto-generated method stub
System.out.println("投币成功,请按出货按钮!");
mVendingMachine.setState(mVendingMachine.mHasCoin);

@Override
public void returnCoin()

// TODO Auto-generated method stub
System.out.println("您还没有投币!");


@Override
public void pressButton()

// TODO Auto-generated method stub
System.out.println("请您先投币!");


@Override
public void appearCola()

// TODO Auto-generated method stub

@Override
public void printState()

// TODO Auto-generated method stub
System.out.println("=========售卖中=========");

/***
* 售空状态类
* @author birdlove1987
*
*/
public class SoldOutState implements State
private VendingMachine mVendingMachine;
public SoldOutState(VendingMachine mCandyMachine)

this.mVendingMachine=mVendingMachine;

@Override
public void insertCoin()

// TODO Auto-generated method stub
System.out.println("请不要投币了,售货机里已经没有可乐了!");


@Override
public void returnCoin()

// TODO Auto-generated method stub
System.out
.println("您还没有投币!");

@Override
public void pressButton()

// TODO Auto-generated method stub
System.out.println("对不起,可乐已售空!");


@Override
public void appearCola()

// TODO Auto-generated method stub

@Override
public void printState()
// TODO Auto-generated method stub
System.out.println("=========售空=========");



/***
* 已投币状态类
* @author birdlove1987
*
*/
public class HasCoin implements State

private VendingMachine mVendingMachine;
public HasCoin(VendingMachine mVendingMachine)

this.mVendingMachine = mVendingMachine;

@Override
public void insertCoin()

// TODO Auto-generated method stub
System.out.println("售货机里以及有硬币了,请勿重复投币!");

@Override
public void returnCoin()

// TODO Auto-generated method stub
System.out.println("请在退币口收好您的硬币");
mVendingMachine.setState(mVendingMachine.mOnReadyState);

@Override
public void pressButton()

// TODO Auto-generated method stub
System.out.println("请稍等,出可乐中!");

//创建随机中奖概率
Random anotherOne = new Random();

//20%的机会再来一瓶
int luck = anotherOne.nextInt(5);
if(luck==0)

mVendingMachine.setState(mVendingMachine.mOneMoreCola);
else

mVendingMachine.setState(mVendingMachine.mSoldState);


@Override
public void appearCola()


@Override
public void printState()

// TODO Auto-generated method stub
System.out.println("=========已投币=========");

/**
* 出可乐状态类
* @author birdlove1987
*
*/
public class SoldState implements State
private VendingMachine mVendingMachine;
public SoldState(VendingMachine mVendingMachine)

this.mVendingMachine=mVendingMachine;

@Override
public void insertCoin()

// TODO Auto-generated method stub
System.out.println("正在出货请勿投币!");

@Override
public void returnCoin()

// TODO Auto-generated method stub
System.out.println("可乐已售出,不能退币");


@Override
public void pressButton()

// TODO Auto-generated method stub
System.out
.println("可乐已出,如想再次购买请再次投币!");

@Override
public void appearCola()

// TODO Auto-generated method stub

mVendingMachine.appearCola();
if (mVendingMachine.getCount() > 0)

mVendingMachine.setState(mVendingMachine.mOnReadyState);

else

System.out.println("对不起,可乐已经售空了,请勿在投币!");
mVendingMachine.setState(mVendingMachine.mSoldOutState);



@Override
public void printState()

// TODO Auto-generated method stub
System.out.println("=========出货中=========");


/***
* 再来一瓶类
* @author birdlove1987
*
*/
public class OneMoreCola implements State
private VendingMachine mVendingMachine;
public OneMoreCola(VendingMachine mVendingMachine)

this.mVendingMachine = mVendingMachine;

@Override
public void insertCoin()

// TODO Auto-generated method stub
System.out.println("正在出货请勿投币!");

@Override
public void returnCoin()

// TODO Auto-generated method stub
System.out.println("可乐已售出,不能退币");

@Override
public void pressButton()

// TODO Auto-generated method stub
System.out.println("请稍等,出可乐中!");

@Override
public void appearCola()

// TODO Auto-generated method stub

mVendingMachine.appearCola();
if (mVendingMachine.getCount() == 0)

mVendingMachine.setState(mVendingMachine.mSoldOutState);

else

System.out.println("恭喜你获得了再来一瓶,马上为您再出一瓶可乐");
mVendingMachine.appearCola();
if (mVendingMachine.getCount() > 0)

mVendingMachine.setState(mVendingMachine.mOnReadyState);

else

System.out.println("对不起,可乐已经售空了,请勿在投币!");
mVendingMachine.setState(mVendingMachine.mSoldOutState);



@Override
public void printState()

// TODO Auto-generated method stub
System.out.println("=========再来一瓶=========");





构建自动贩售机类


/**
* 自动售货机类
* @author birdlove1987
*
*/
public class VendingMachine
//状态类引用
State mSoldOutState;
State mOnReadyState;
State mHasCoin;
State mSoldState;
State mOneMoreCola;

//目前状态
private State state;

//可乐计数器
private int count = 0;
//构造函数
public VendingMachine(int count)

this.count = count;
mSoldOutState = new SoldOutState(this);
mOnReadyState = new OnReadyState(this);
mHasCoin = new HasCoin(this);
mSoldState = new SoldState(this);
mOneMoreCola = new OneMoreCola(this);
if (count > 0)

state = mOnReadyState;

else

state = mSoldOutState;


//设置状态函数
public void setState(State state)

this.state = state;

//投币函数
public void insertCoin()

state.insertCoin();


//退币函数
public void returnCoin()

state.returnCoin();


//按出可乐按钮函数
public void pressButton()

state.pressButton();
state.appearCola();

//出可乐函数
void appearCola()

// TODO Auto-generated method stub
if (count > 0)

count = count - 1;
System.out.println("出货口,滚出了一瓶可乐!");


//可乐计数函数
public int getCount()

return count;


//打印状态函数
public void printState()

state.printState();




最后写一个测试类测试一下


/**
* 测试类
* @author birdlove1987
*
*/
public class MainTest
public static void main(String[] args)


//实例化自动贩售机对象
VendingMachine mVendingMachine = new VendingMachine(10);

//打印状态
mVendingMachine.printState();
//投币
mVendingMachine.insertCoin();

//打印状态
mVendingMachine.printState();
//按出可乐按钮
mVendingMachine.pressButton();
//打印状态
mVendingMachine.printState();
//投币
mVendingMachine.insertCoin();

//打印状态
mVendingMachine.printState();
//按出可乐按钮
mVendingMachine.pressButton();
//打印状态
mVendingMachine.printState();









卧槽!一次都没中奖,什么鬼!!!不行,买买买!!!




中了一次。。。好吧,我来作弊一下。。调到100%




哈哈哈!


状态模式的优点
    1.状态模式将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
    2.将与状态有关的行为封装到一个类中,方便地增加新的状态,只需改变对象状态即可改变对象的行为。 
    3.提供代码复用性,降低了程序的某些耦合性。   
     
状态模式的缺点
    1.有时候状态类会很多,而且逻辑复杂。

状态模式适用场景
    1、对象的行为依赖于它的状态,并且其行为依据它的状态改变而改变。 
    2、代码中包含大量与对象状态有关的条件语句









推荐阅读
  • 本文详细介绍了Java中org.w3c.dom.Text类的splitText()方法,通过多个代码示例展示了其实际应用。该方法用于将文本节点在指定位置拆分为两个节点,并保持在文档树中。 ... [详细]
  • 在前两篇文章中,我们探讨了 ControllerDescriptor 和 ActionDescriptor 这两个描述对象,分别对应控制器和操作方法。本文将基于 MVC3 源码进一步分析 ParameterDescriptor,即用于描述 Action 方法参数的对象,并详细介绍其工作原理。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ... [详细]
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • Android 渐变圆环加载控件实现
    本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
  • 本文详细介绍了如何构建一个高效的UI管理系统,集中处理UI页面的打开、关闭、层级管理和页面跳转等问题。通过UIManager统一管理外部切换逻辑,实现功能逻辑分散化和代码复用,支持多人协作开发。 ... [详细]
  • 本文详细介绍了 Apache Jena 库中的 Txn.executeWrite 方法,通过多个实际代码示例展示了其在不同场景下的应用,帮助开发者更好地理解和使用该方法。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
  • 利用存储过程构建年度日历表的详细指南
    本文将介绍如何使用SQL存储过程创建一个完整的年度日历表。通过实例演示,帮助读者掌握存储过程的应用技巧,并提供详细的代码解析和执行步骤。 ... [详细]
author-avatar
Lai-flip_179
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有